package com.telit.firecommand.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.telit.common.config.SmsAliServerConfig;
import com.telit.common.constant.MsgIdentificationConstants;
import com.telit.common.dto.SmsRealFireDto;
import com.telit.common.util.SmsUtils;
import com.telit.firecommand.dao.FireQueryDao;
import com.telit.firecommand.dao.GeoXzqhCunDao;
import com.telit.firecommand.dto.FirePushAlarmsDTO;
import com.telit.firecommand.dto.MisreportFireDTO;
import com.telit.firecommand.dto.NoticePushDTO;
import com.telit.firecommand.dto.PushSocketDTO;
import com.telit.firecommand.enums.FireSourceTypeStatus;
import com.telit.firecommand.facade.MsgFireTriggerFacadeService;
import com.telit.firecommand.service.CommMsgCenterLogService;
import com.telit.firecommand.service.SmsService;
import com.telit.firecommand.vo.FireQueryAllListVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.Charset;


/**
 * 短信服务
 *
 * @author yuezhuang
 * @date 2022-09-13
 */
@Slf4j
@Service
public class SmsServiceImpl implements SmsService {

    @Autowired
    private SmsAliServerConfig smsAliServerConfig;

    @Autowired
    private MsgFireTriggerFacadeService msgFireTriggerFacadeService;
//
//    @Autowired
//    private WatchmanService watchmanService;

    @Autowired
    private FireQueryDao fireQueryDao;

    @Autowired
    private GeoXzqhCunDao geoXzqhCunDao;

    @Autowired
    private CommMsgCenterLogService commMsgCenterLogService;

    @Value("${spring.profiles.active}")
    private String env;

    /**
     * 发送短信
     *
     *
     * @return 发送结果，不保证一定发送成功，不保证为阿里短信是否成功发送，只保证触发
     * @throws Exception 异常信息
     */
    @Override
    @Transactional
    public boolean sendSms(NoticePushDTO noticePushDTO) throws Exception {

        FireQueryAllListVO fireDetailByFireId = fireQueryDao.findFireDetailByFireId(noticePushDTO.getFireId());
        if (ObjectUtil.isNotNull(fireDetailByFireId)) {
            //根据行政区划代码查询地址
            if (fireDetailByFireId.getDistrictCode() != null) {
                fireDetailByFireId.setDistrictCodeName(geoXzqhCunDao.queryNameByCode(fireDetailByFireId.getDistrictCode(), fireDetailByFireId.getDistrictCode().length()));
            }
            if (StringUtils.isNotBlank(fireDetailByFireId.getSourceType())) {
                fireDetailByFireId.setSourceTypeName(FireSourceTypeStatus.code2Str(Integer.parseInt(fireDetailByFireId.getSourceType())));
            }
        }
//        //查询火情详情
//        DataReturn dataReturn = alarmsFeignClient.qryAlarmsInfo(fireId);
//        if (!ResultCode.SUCCESS.getCode().equals(dataReturn.getCode())
//                && !FireConstant.ALARMS_SUCCESS_CODE.equals(dataReturn.getCode())) {
//            throw new ForestBaseException(dataReturn.getErrorMsg());
//        }
 //       FireAlarmsDTO fireAlarmsDTO = JSON.parseObject(JSON.toJSONString(dataReturn.getData()), FireAlarmsDTO.class);

        //根据模板类型获取模板实体类
        @SuppressWarnings("unchecked") final Class<Object> clazz = smsAliServerConfig.getParamClass(
                Convert.toStr(noticePushDTO.getStatus()));
        //根据模板类型获取模板code
        final String template = smsAliServerConfig.getTemplate(Convert.toStr(noticePushDTO.getStatus()));
        if (ObjectUtil.isNull(clazz) || StrUtil.isEmpty(template)) {
            log.error("短信调用失败,约束火情! status[{}]", noticePushDTO.getStatus());
            return false;
        }
        final Object objParam = ClassUtil.createInstance(clazz, Boolean.FALSE);
        //生成 交互序列号
        final String interactiveCode = buildUrl(fireDetailByFireId);
        //临时处理 暂时不处理3
        if (noticePushDTO.getStatus() == 1) {
            final SmsRealFireDto dto = (SmsRealFireDto) objParam;
            dto.setCode(interactiveCode)
                    .setAddress(fireDetailByFireId.getPlaceName());

            //非生产环境不推送短信
            if (!("dev".equals(env) || "test".equals(env))) {
                SmsUtils.sendContent(noticePushDTO.getMobileList(), template, dto);
            }

            //生成火情消息记录
            commMsgCenterLogService.saveFireMsg(noticePushDTO.getMobileList(),
                    Long.parseLong(noticePushDTO.getFireId()));
        }
        //将火情状态改成1
        if (StringUtils.isNotBlank(noticePushDTO.getIsOpen())&&noticePushDTO.getIsOpen().equals("1")) {
            MisreportFireDTO misreportFireDTO = new MisreportFireDTO();
            misreportFireDTO.setFireId(noticePushDTO.getFireId());
            misreportFireDTO.setFireJudgmentType(1);
      //      watchmanService.misreport(misreportFireDTO);
        }
        return true;
    }

    @Override
    public boolean pushSocket(PushSocketDTO pushSocketDTO) {
        FirePushAlarmsDTO dto = new FirePushAlarmsDTO();
        dto.setFireId(pushSocketDTO.getFireId());
        dto.setLongitude(pushSocketDTO.getLongitude());
        dto.setLatitude(pushSocketDTO.getLatitude());
//        if (StringUtils.isNotBlank(pushSocketDTO.getAreaCode())) {
//            dto.setAreaCode(pushSocketDTO.getAreaCode().substring(0,6));
//        }
        dto.setAreaCode(pushSocketDTO.getAreaCode());
        dto.setSourceType(pushSocketDTO.getSourceType());
        dto.setSourceTypeName(pushSocketDTO.getSourceTypeName());
        dto.setFlag(MsgIdentificationConstants.WATCH_OK);

        msgFireTriggerFacadeService.pushMsg(dto);
        //推送消息到web端
//        SendMessageDTO sendMessageDTO = new SendMessageDTO();
//        sendMessageDTO.setFlag("web");
//        sendMessageDTO.setMsg(JSON.toJSONString(DataReturn.ok(MsgIdentificationConstants.WATCH_OK, dto)));
//        communicateFeignClient.sendMsg(sendMessageDTO);
        return true;
    }


    /**
     * 直接生成后端接口url
     *
     * @param fireDetailByFireId 火情信息
     *
     * @return url返回
     */
    public String buildUrl(FireQueryAllListVO fireDetailByFireId) {
        return buildInfo(fireDetailByFireId);
    }

    /**
     * 根据火情id 构造key 和数据
     *
     * @return key值
     */
    public String buildInfo(FireQueryAllListVO fireDetailByFireId) {
        return buildKey(fireDetailByFireId.getFireId());
    }

    /**
     * 根据 fireId +当前时间毫秒构造 key，通过md5生成唯一签名， bcd 转二进制 压缩数字后存放 4位int
     *
     * @param fireId 火情id
     *
     * @return 生成key
     */
    @SuppressWarnings("all")
    private String buildKey(String fireId) {
        //fireId 和 毫秒组成随机数
        final String fireIdRamdom = StrUtil.format("{}{}", fireId, DateUtil.thisMillsecond());
        final String md5 = MD5.create().digestHex(fireIdRamdom, Charset.defaultCharset());
        final String[] str = shortUrl(md5);
        return Convert.toStr(str[2]);
    }

    public static String[] shortUrl(String hex) {
        // 要使用生成 URL 的字符
        final String[] chars = new String[]{"a", "b", "c", "d", "e", "f", "g", "h",
                "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
                "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H",
                "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
                "U", "V", "W", "X", "Y", "Z"
        };
        String[] resUrl = new String[4];
        for (int i = 0; i < 4; i++) {
            String sTempSubString = hex.substring(i * 8, i * 8 + 8);
            long lHexLong = 0x3FFFFFFF & Long.parseLong(sTempSubString, 16);
            String outChars = "";
            for (int j = 0; j < 6; j++) {
                long index = 0x0000003D & lHexLong;
                outChars += chars[(int) index];
                lHexLong = lHexLong >> 5;
            }
            // 把字符串存入对应索引的输出数组
            resUrl[i] = outChars;
        }
        return resUrl;
    }

}
